package enron;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;

import javax.swing.AbstractCellEditor;
import javax.swing.JComponent;
import javax.swing.JFormattedTextField;
import javax.swing.JLabel;
import javax.swing.JSpinner;
import javax.swing.JTable;
import javax.swing.SpinnerModel;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.table.TableCellEditor;
import javax.swing.text.DefaultFormatter;

public class SpinnerEditor extends AbstractCellEditor implements
		TableCellEditor {
	private static final long serialVersionUID = 4924618423142903487L;
	protected TableCellEditor delegate;
	private JSpinner spinner = new JSpinner();
	private JLabel outerLabel = new JLabel();
	private JFormattedTextField textField;
	private Boolean valueSet = false;

	// Initializes the spinner.
	public SpinnerEditor(SpinnerModel model, TableCellEditor defaultEditor) {
		delegate = defaultEditor;
		outerLabel.setLayout(new BorderLayout());
		outerLabel.setName("Table.spinnerCellEditor");
		spinner.setModel(model);
		spinner.putClientProperty(this.getClass(), this);
		
		this.addCellEditorListener(new CellEditorListener(){

			@Override
			public void editingCanceled(ChangeEvent e) {
				//((JSpinner.NumberEditor)spinner.getEditor()).dispatchEvent(new ActionEvent(spinner.getEditor(), ActionEvent.ACTION_PERFORMED, "editingCanceled"));
				//((SpinnerEditor)e.getSource()).spinner.setValue(0L);
			}

			@Override
			public void editingStopped(ChangeEvent e) {
				//((JSpinner.NumberEditor)spinner.getEditor()).dispatchEvent(new ActionEvent(spinner.getEditor(), ActionEvent.ACTION_PERFORMED, "editingStopped"));
				//spinner.
				//((SpinnerEditor)e.getSource()).spinner.setValue(0L);
			}
		});
		spinner.setEditor(new JSpinner.NumberEditor(spinner));
		textField = ((JSpinner.NumberEditor)spinner.getEditor()).getTextField();
		((DefaultFormatter)textField.getFormatter()).setCommitsOnValidEdit(true);

		textField.addFocusListener( new FocusListener() {
			public void focusGained( FocusEvent fe ) {
				//System.err.println("Got focus");
				SwingUtilities.invokeLater( new Runnable() {
					public void run() {
						if ( valueSet ) {
							textField.selectAll();
						}
					}
				});
			}
			public void focusLost( FocusEvent fe ) {
			}
		});
		textField.addActionListener( new ActionListener() {
			public void actionPerformed( ActionEvent ae ) {
				stopCellEditing();
			}
		});
		spinner.setBorder(new EmptyBorder(0,0,0,0));
		outerLabel.add(spinner);
	}

	// Prepares the spinner component and returns it.
	public Component getTableCellEditorComponent(JTable table, Object value,
			boolean isSelected, int row, int column) {
		JComponent c = (JComponent)delegate.getTableCellEditorComponent(table, value, 
				isSelected, row, column);
		//respect insets and focus
		outerLabel.setBorder(c.getBorder());
		//copy opacity
		outerLabel.setOpaque(c.isOpaque());
		//apply background
		outerLabel.setBackground(c.getBackground());    
		//apply foreground
		spinner.getEditor().setForeground(c.getForeground());
		if(value == null) {
			spinner.setValue(0);
		} else {
			spinner.setValue(value);
		}
		valueSet = true;
		//return spinner;
		return outerLabel;
	}

	@Override
	public Object getCellEditorValue() {
		return spinner.getValue();
	}
}
